home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / passwd+ / pwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  7.1 KB  |  357 lines

  1. /*
  2.  * update the password file and (if necessary)
  3.  * any associated DBM database
  4.  */
  5. #include "passwd.h"
  6. #include <signal.h>
  7. #ifdef YPPASSWD
  8. #include <rpcsvc/yppasswd.h>
  9. #endif
  10. #ifdef DBMLIB
  11. #    include <dbm.h>
  12. #endif
  13.  
  14. #ifdef SYSV_PWFUNC
  15. /*
  16.  * library function
  17.  */
  18. extern struct passwd *fgetpwent();    /* get password entry from any file */
  19. #endif
  20.  
  21. /*
  22.  * some definitions
  23.  */
  24. #define PF_PLATE    "./ptmpXXXXX"    /* original temporary file */
  25. #define PF_TEMP        "./ptmp"    /* lock file */
  26. #define PW_CANTLOCK    -1        /* error code -- locking failed */
  27. #define    PW_CANTOPEN    -2        /* error code -- open failed */
  28. #define PW_CANTRENAME    -3        /* error code -- rename failed */
  29. #define PW_NOCHANGE    -4        /* error code -- no passwd entry */
  30.  
  31. /*
  32.  * global variables
  33.  */
  34. char *pf_name = "/etc/passwd";        /* password file name */
  35. char *pf_tnam;                /* name of temporary file */
  36. FILE *pf_fp;                /* pointer to real password file */
  37. FILE *pf_tfp;                /* pointer to temporary file */
  38. int pf_errno;                /* error number */
  39.  
  40. /*
  41.  * library functions
  42.  */
  43. extern char *mktemp();            /* makes a temp file name */
  44.  
  45. #ifndef NOSETPWFILE
  46. /*
  47.  * change the password file's name
  48.  */
  49. name_pwd(name)
  50. char *name;
  51. {
  52.     /*
  53.      * reassociate the name
  54.      */
  55.     pf_name = name;
  56. }
  57. #endif
  58.  
  59. check_age(p)
  60. struct passwd *p;
  61. {
  62. #ifdef AGE_FIELD
  63.     long aging, now, a64l(), time();
  64.     int min, max;
  65.     if (*p->pw_age == NULL)
  66.         return(1);
  67.     aging = a64l(p->pw_age);
  68.     now = time(0L) / (60 * 60 * 24 * 7);
  69.     max = aging & 077;
  70.     min = (aging >> 6) & 077;
  71.     aging >>= 12;
  72.     return(max >= min && aging + min <= now);
  73. #else
  74.     return(1);
  75. #endif
  76. }
  77.  
  78. update_pwd(p)
  79. struct passwd *p;        /* new password structure */
  80. {
  81.     char nbuf[BUFSIZ];        /* buffer for passwords being read */
  82.     char obuf[BUFSIZ];        /* buffer for new entry */
  83.     register char *q, *s;        /* used for quick name comparison */
  84.     int retval = PW_NOCHANGE;    /* return value */
  85. #ifdef DBMLIB
  86.     union {
  87.         int i;                 /* as an integer */
  88.         char c[1];            /* as a character */
  89.     } itoc;                /* maps integer into char storage */
  90.     datum key;            /* key data is to be stored under */
  91.     datum newrec;            /* record to be stored */
  92. #endif
  93.  
  94.     /*
  95.      * disable ALL signals at this point
  96.      */
  97.     sigoff();
  98.  
  99.     /*
  100.      * open the temporary password file
  101.      */
  102.     umask(022);
  103.     pf_tnam = mktemp(PF_PLATE);
  104.     if ((pf_tfp = fopen(pf_tnam, "w")) == FI_NULL){
  105.         pf_errno = errno;
  106.         retval = PW_CANTOPEN;
  107.         goto cantlock;
  108.     }
  109.  
  110.     /*
  111.      * lock the password file
  112.      */
  113.     if (link(pf_tnam, PF_TEMP) < 0){
  114.         pf_errno = errno;
  115.         retval = PW_CANTLOCK;
  116.         goto cantlock;
  117.     }
  118.     
  119.     /*
  120.      * copy the new password structure
  121.      */
  122. #ifdef AGE_FIELD
  123.     { long aging, thischange, a64l(), time(); char *l64a();
  124.     aging = a64l(p->pw_age);
  125.     thischange = time(0L) / (60 * 60 * 24 * 7);
  126.     aging = (thischange<<12)|(aging&07777);
  127.     p->pw_age = l64a(aging);
  128.     SPRINTF(obuf, "%s:%s,%s:%d:%d:%s:%s:%s\n",
  129.             p->pw_name, p->pw_passwd, p->pw_age, p->pw_uid,
  130.                 p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);
  131.     }
  132. #else
  133.     SPRINTF(obuf, "%s:%s:%d:%d:%s:%s:%s\n",
  134.             p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid,
  135.                     p->pw_gecos, p->pw_dir, p->pw_shell);
  136. #endif
  137.  
  138.     /*
  139.      * open the password file
  140.      */
  141.     if ((pf_fp = fopen(pf_name, "r")) == FI_NULL){
  142.         pf_errno = errno;
  143.         retval = PW_CANTOPEN;
  144.         goto getout;
  145.     }
  146.  
  147.  
  148.     /*
  149.      * copy the password file into the temporary one
  150.      */
  151.     while(fgets(nbuf, BUFSIZ, pf_fp) != NULL){
  152.         for(s = nbuf, q = p->pw_name; *s && *s != ':'; s++, q++)
  153.             if (*s != *q)
  154.                 break;
  155.         if (*s == ':' && *q == '\0') {
  156.             fputs(obuf, pf_tfp);
  157.             retval = 0;
  158.         } else
  159.             fputs(nbuf, pf_tfp);
  160.     }
  161.     if (retval == PW_NOCHANGE) {
  162. #ifdef YPPASSWD
  163.         if(yppasswd(oldpassword, p) == 0) {
  164.             retval = 0;
  165.         }
  166. #endif
  167.         goto getout;
  168.     }
  169.  
  170.     /*
  171.      * close the temporary file and the real one
  172.      */
  173.     (void) fclose(pf_tfp);
  174.     pf_tfp = FI_NULL;
  175.     (void) fclose(pf_fp);
  176.     pf_fp = FI_NULL;
  177.  
  178.     /*
  179.      * now relink; note the lock file is still there
  180.      */
  181. #ifdef RENAME
  182.     if (RENAME(pf_tnam, pf_name) < 0){
  183. #else
  184.     if (unlink(pf_name) >= 0
  185.         && link(pf_tnam, pf_name) >= 0
  186.             && unlink(pf_tnam) >= 0){
  187. #endif
  188.         pf_errno = errno;
  189.         retval = PW_CANTRENAME;
  190.     }
  191.  
  192. #ifdef DBMLIB
  193.     /*
  194.      * see if there is a corresponding dbm file
  195.      */
  196.     if (dbminit(pf_name) >= 0){
  197.         register int i;        /* counter in a for loop */
  198.         /*
  199.          * there is; make the new datum in nbuf
  200.          */
  201.         q = nbuf;
  202.         for(s = p->pw_name; *q++ = *s++; );    /* pw_name */
  203.         for(s = p->pw_passwd; *q++ = *s++; );    /* pw_passwd */
  204.         itoc.i = p->pw_uid;            /* pw_uid */
  205.         for(i = 0; i < sizeof(int); i++)
  206.             *q++ = itoc.c[i];
  207.         itoc.i = p->pw_gid;            /* pw_gid */
  208.         for(i = 0; i < sizeof(int); i++)
  209.             *q++ = itoc.c[i];
  210.         itoc.i = p->pw_quota;            /* pw_quota */
  211.         for(i = 0; i < sizeof(int); i++)
  212.             *q++ = itoc.c[i];
  213.         for(s = p->pw_comment; *q++ = *s++; );    /* pw_comment */
  214.         for(s = p->pw_gecos; *q++ = *s++; );    /* pw_gecos */
  215.         for(s = p->pw_dir; *q++ = *s++; );    /* pw_dir */
  216.         for(s = p->pw_shell; *q++ = *s++; );    /* pw_shell */
  217.         /*
  218.          * now the size of the data
  219.          */
  220.         newrec.dptr = nbuf;
  221.         newrec.dsize = q - nbuf;
  222.         /*
  223.          * store it under the UID and the name
  224.          */
  225.         itoc.i = p->pw_uid;
  226.         key.dptr = itoc.c;    key.dsize = sizeof(int);
  227.         store(key, newrec);
  228.         key.dptr = p->pw_name;    key.dsize = strlen(p->pw_name);
  229.         store(key, newrec);
  230.     }
  231. #endif
  232.  
  233. getout:
  234.     /*
  235.      * Only remove lock file if this program obtained it
  236.      */
  237.     (void) unlink(PF_TEMP);
  238. cantlock:
  239.     /*
  240.      * some clean up
  241.      */
  242.     if (pf_tfp != FI_NULL)
  243.         (void) fclose(pf_tfp);
  244.     if (pf_fp != FI_NULL)
  245.         (void) fclose(pf_fp);
  246.     (void) unlink(pf_tnam);
  247.  
  248.     /*
  249.      * re-enable ALL signals at this point
  250.      */
  251.     sigon();
  252.  
  253.     /*
  254.      * good!
  255.      */
  256.     return(retval);
  257. }
  258.  
  259. /*
  260.  * get a name; built on other library routines
  261.  */
  262. struct passwd *mgpwnam(name)
  263. char *name;            /* name being looked for */
  264. {
  265. #ifdef FGETPWENT
  266.     register struct passwd *p;    /* points to returning structure */
  267.     /*
  268.      * open the password file
  269.      */
  270.     if ((pf_fp = fopen(pf_name, "r")) == FI_NULL){
  271.         perror(pf_name);
  272.         exit(1);
  273.     }
  274.     /*
  275.      * scan the file looking for the right line
  276.      */
  277.     while((p = FGETPWENT(pf_fp)) != PW_NULL)
  278.         if (strcmp(p->pw_name, name) == 0)
  279.             break;
  280.  
  281.     /*
  282.      * close the file and return the right structure
  283.      */
  284.     (void) fclose(pf_fp);
  285.     return(p);
  286. #else
  287. #ifdef SETPWFILE
  288.     register struct passwd *p;    /* points to returning structure */
  289.     /*
  290.      * set the password file name
  291.      */
  292.     SETPWFILE(pf_name);
  293.     /*
  294.      * get the required structure
  295.      */
  296.     p = getpwnam(name);
  297.     /*
  298.      * close the file and return the data
  299.      */
  300.     endpwent();
  301.     return(p);
  302. #else
  303.     return(getpwnam(name));
  304. #endif
  305. #endif
  306. }
  307.  
  308. /*
  309.  * get a uid; built on other library routines
  310.  */
  311. struct passwd *mgpwuid(uid)
  312. int uid;            /* uid being looked for */
  313. {
  314. #ifdef FGETPWENT
  315.     register struct passwd *p;    /* points to returning structure */
  316.     /*
  317.      * open the password file
  318.      */
  319.     if ((pf_fp = fopen(pf_name, "r")) == FI_NULL){
  320.         perror(pf_name);
  321.         exit(1);
  322.     }
  323.     /*
  324.      * scan the file looking for the right line
  325.      */
  326.     while((p = FGETPWENT(pf_fp)) != PW_NULL)
  327.         if (uid == p->pw_uid)
  328.             break;
  329.  
  330.     /*
  331.      * close the file and return the right structure
  332.      */
  333.     (void) fclose(pf_fp);
  334.     return(p);
  335. #else
  336. #ifdef SETPWFILE
  337.     register struct passwd *p;    /* points to returning structure */
  338.     /*
  339.      * set the password file name
  340.      */
  341.     SETPWFILE(pf_name);
  342.     /*
  343.      * get the required structure
  344.      */
  345.     p = getpwuid(uid);
  346.     /*
  347.      * close the file and return the data
  348.      */
  349.     endpwent();
  350.     return(p);
  351. #else
  352.     return(getpwuid(uid));
  353. #endif
  354. #endif
  355. }
  356.  
  357.